package com.wywah.yunduo.security.supports.password;

import com.wywah.yunduo.security.utils.ClientUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;

public class YunduoBasicAuthenticationConverter extends BasicAuthenticationConverter {
    private final AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;

    public YunduoBasicAuthenticationConverter() {
        this(new WebAuthenticationDetailsSource());
    }

    public YunduoBasicAuthenticationConverter(AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
        super(authenticationDetailsSource);
        this.authenticationDetailsSource = authenticationDetailsSource;
    }

    @Override
    public UsernamePasswordAuthenticationToken convert(HttpServletRequest request) {
        UsernamePasswordAuthenticationToken convert = super.convert(request);
        if(Objects.isNull(convert)){
            String header = request.getHeader(ClientUtils.CLIENG_BASICE_HEADER);
            if (header == null) {
                return null;
            } else {
                header = header.trim();
                if (!StringUtils.startsWithIgnoreCase(header, "Basic")) {
                    return null;
                } else if (header.equalsIgnoreCase("Basic")) {
                    throw new BadCredentialsException("Empty basic authentication token");
                } else {
                    byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
                    byte[] decoded = this.decode(base64Token);
                    String token = new String(decoded, this.getCredentialsCharset(request));
                    int delim = token.indexOf(":");
                    if (delim == -1) {
                        throw new BadCredentialsException("Invalid basic authentication token");
                    } else {
                        UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.unauthenticated(token.substring(0, delim), token.substring(delim + 1));
                        result.setDetails(this.authenticationDetailsSource.buildDetails(request));
                        return result;
                    }
                }
            }
        }
        return convert;
    }

    private byte[] decode(byte[] base64Token) {
        try {
            return Base64.getDecoder().decode(base64Token);
        } catch (IllegalArgumentException var3) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }
    }
}
